<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>rocket mq 实现分布式事物</title>
    <meta content="width=device-width,minimum-scale=1,maximum-scale=1,user-scalable=no" id="viewport" name="viewport">
</head>
<!-- import Vue.js -->
<script src="https://vuejs.org/js/vue.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<!-- import stylesheet -->
<link rel="stylesheet" href="https://unpkg.com/iview/dist/styles/iview.css">
<!-- import iView -->
<script src="https://unpkg.com/iview/dist/iview.min.js"></script>
<body>
<div id="app">

    <div style="background:#f8f8f8;padding: 25px">
        <row gutter="10">
            <i-col span="12" v-for="bank in banks">
                <card>
                    <p slot="title">银行账户</p>
                    <p>
                        <icon type="md-person" size="18" color="#8043d4"></icon>
                        ：{{bank.accountName}}
                    </p>
                    <br/>
                    <p>
                        <icon type="logo-yen" size="16" color="#ff4400"></icon>
                        ：{{bank.money}}
                    </p>
                </card>
            </i-col>
        </row>

        <br/>
        <alert show-icon>
            转账异常触发规则
            <icon type="ios-bulb-outline" slot="icon"></icon>
            <template slot="desc">
                当转账金额<b style="color: #ff9900">=10</b>时，服务<b style="color: #ed4014">zhangsan</b>触发异常
                <br/>
                当转账金额<b style="color: #ff9900">=15</b>时，服务<b style="color: #ed4014">lisi</b>触发异常
            </template>
        </alert>
        <br/>

        <row gutter="10">

            <i-col span="6">
                <h2>
                    本地事物措施
                </h2>
                <i-form :label-width="40">

                    <alert type="warning">
                        <template slot="desc">
                            当转账金额<b style="color: #ff9900">=10</b>时，<b style="color: #ed4014">zhangsan</b>服务触发异常,但是<b style="color: #ed4014">lisi</b>却收到转账
                            <br/>
                            当转账金额<b style="color: #ff9900">=15</b>时，<b style="color: #ed4014">lisi</b>触发异常,这时两个账户钱都不会变
                        </template>
                    </alert>

                    <form-item label="账户">
                        <i-input type="text" disabled size="large" v-model="account1.accountName" placeholder="对方账户"></i-input>
                    </form-item>

                    <form-item label="金额">
                        <i-input type="number" size="large" v-model="account1.money" placeholder="转账金额"></i-input>
                    </form-item>

                    <form-item style="text-align: center;">
                        <i-button type="primary" @click="transfer()">转账</i-button>
                    </form-item>
                </i-form>
            </i-col>

            <i-col span="6">
                <h2>
                    可靠消息最终一致性(rocketmq)
                </h2>

                <i-form :label-width="40">
                    <alert type="warning">
                        <template slot="desc">
                            当转账金额<b style="color: #ff9900">=10</b>时，<b style="color: #ed4014">zhangsan</b>服务触发异常,<b style="color:#ed4014">不发送事物消息</b>
                            <br/>
                            当转账金额<b style="color: #ff9900">=15</b>时，<b style="color: #ed4014">lisi</b>触发异常,<b style="color:#ed4014">但消息会一直通知等<b style="color: #19be6b">lisi</b>完成消费</b>
                        </template>
                    </alert>

                    <form-item label="账户">
                        <i-input type="text" disabled size="large" v-model="account2.accountName" placeholder="对方账户"></i-input>
                    </form-item>

                    <form-item label="金额">
                        <i-input type="number" size="large" v-model="account2.money" placeholder="转账金额"></i-input>
                    </form-item>

                    <form-item style="text-align: center;">
                        <i-button type="primary" @click="txTransfer()">转账</i-button>
                    </form-item>
                </i-form>

            </i-col>

            <i-col span="6">
                <h2>
                    最大努力通知方式(rocketmq)
                </h2>

                <i-form :label-width="40">
                    <alert type="warning">
                        <template slot="desc">
                            当转账金额<b style="color: #ff9900">=10</b>时，<b style="color: #ed4014">zhangsan</b>服务触发异常,<b style="color:#ed4014">不发送事物消息</b>
                            <br/>
                            当转账金额<b style="color: #ff9900">=15</b>时，<b style="color: #ed4014">lisi</b>触发异常,<b style="color:#ed4014">但消息会一直通知等<b style="color: #19be6b">lisi</b>完成消费</b>
                        </template>
                    </alert>

                    <form-item label="账户">
                        <i-input type="text" disabled size="large" v-model="account3.accountName" placeholder="对方账户"></i-input>
                    </form-item>

                    <form-item label="金额">
                        <i-input type="number" size="large" v-model="account3.money" placeholder="转账金额"></i-input>
                    </form-item>

                    <form-item style="text-align: center;">
                        <i-button type="primary" @click="msgTransfer()">转账</i-button>
                    </form-item>
                </i-form>
            </i-col>

            <i-col span="6">
                <h2>
                    Seata 方案
                </h2>

                <i-form :label-width="40">
                    <alert type="warning">
                        <template slot="desc">
                            当<b style="color: #ed4014">zhangsan</b>服务调用<b style="color: #ed4014">lisi</b>时(线程模拟睡眠五秒观察数据),数据库已经commit了这就是跟2pc的区别,并且数据库表<b style="color: #ed4014">undo_log</b>产生一条记录,等全部rpc执行完成了有异常则执行回滚,没有异常则删除日志
                        </template>
                    </alert>

                    <form-item label="账户">
                        <i-input type="text" disabled size="large" v-model="account4.accountName" placeholder="对方账户"></i-input>
                    </form-item>

                    <form-item label="金额">
                        <i-input type="number" size="large" v-model="account4.money" placeholder="转账金额"></i-input>
                    </form-item>

                    <form-item style="text-align: center;">
                        <i-button type="primary" @click="seataTransfer()">转账</i-button>
                    </form-item>
                </i-form>
            </i-col>
        </row>
    </div>
</div>
</body>
<script>
  new Vue({
    el: '#app',
    data: {
      banks: [],
      account1: {
        accountName: 'lisi',
        money: 10
      },
      account2: {
        accountName: 'lisi',
        money: 10
      },
      account3: {
        accountName: 'lisi',
        money: 10
      }
      ,
      account4: {
        accountName: 'lisi',
        money: 10
      }
    },
    mounted: function() {
      this.initBank();
    },
    methods: {
      // 转账
      transfer() {
        let that = this;
        that.$Spin.show({
          render: (h) => {
            return h('div', [
              h('Icon', {
                'class': 'demo-spin-icon-load',
                props: {
                  type: 'ios-loading',
                  size: 18
                }
              }),
              h('div', 'Loading')
            ])
          }
        });
        axios.post("/bank/transfer", that.account1)
             .then(function( res ) {
               that.$Message.success({
                 content: '转账成功',
                 duration: 10,
                 closable: true});
             })
             .catch(function( ex ) {
               console.log(ex);
               that.$Message.error({
                 content: '转账失败',
                 duration: 10,
                 closable: true});
             })
             .then(function() {
               that.initBank();
               setTimeout(() => {
                 that.$Spin.hide();
               }, 1000);
             });

      },
      //事物转账
      txTransfer() {
        let that = this;
        that.$Spin.show({
          render: (h) => {
            return h('div', [
              h('Icon', {
                'class': 'demo-spin-icon-load',
                props: {
                  type: 'ios-loading',
                  size: 18
                }
              }),
              h('div', 'Loading')
            ])
          }
        });
        axios.post("/bank/transfer/tx", that.account2)
             .then(function( res ) {
               that.$Message.success({
                 content: '转账成功',
                 duration: 10,
                 closable: true});
             })
             .catch(function( error ) {
               that.$Message.error({
                 content: '转账失败',
                 duration: 10,
                 closable: true});
             })
             .then(function() {
               that.initBank();
               setTimeout(() => {
                 that.$Spin.hide();
               }, 1000);
             });

      },
      //消息转账
      msgTransfer() {
        let that = this;
        that.$Spin.show({
          render: (h) => {
            return h('div', [
              h('Icon', {
                'class': 'demo-spin-icon-load',
                props: {
                  type: 'ios-loading',
                  size: 18
                }
              }),
              h('div', 'Loading')
            ])
          }
        });
        axios.post("/bank/transfer/msg", that.account3)
             .then(function( res ) {
               that.$Message.success({
                 content: '转账成功',
                 duration: 10,
                 closable: true});
             })
             .catch(function( error ) {
               that.$Message.error({
                 content: '转账失败',
                 duration: 10,
                 closable: true});
             })
             .then(function() {
               that.initBank();
               setTimeout(() => {
                 that.$Spin.hide();
               }, 1000);
             });
      },
      //消息转账
      seataTransfer() {
        let that = this;
        that.$Spin.show({
          render: (h) => {
            return h('div', [
              h('Icon', {
                'class': 'demo-spin-icon-load',
                props: {
                  type: 'ios-loading',
                  size: 18
                }
              }),
              h('div', 'Loading')
            ])
          }
        });
        axios.post("/bank/transfer/seata", that.account4)
             .then(function( res ) {
               that.$Message.success({
                 content: '转账成功',
                 duration: 10,
                 closable: true});
             })
             .catch(function( error ) {
               that.$Message.error({
                 content: '转账失败',
                 duration: 10,
                 closable: true});
             })
             .then(function() {
               that.initBank();
               setTimeout(() => {
                 that.$Spin.hide();
               }, 1000);
             });

      },
      // 加载账户
      initBank() {
        let that = this;
        axios({
          method: 'get',
          url: '/bank',
        }).then(function( res ) {
          that.banks = res.data;
        }).catch(function( error ) {
          that.$Message.error('加载账户异常！');
        });
      }
    }
  });
</script>
<style>
    .ivu-form-label-right {
        padding: 15px;
        margin-top: 5px;
        background-color: #ffffff;
        border: 1px solid #dcdee2;
        border-radius: 5px;
    }
    .vertical-center-modal{
        display: flex;
        align-items: center;
        justify-content: center;

    .ivu-modal{
        top: 0;
    }
    }
</style>
</html>